home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / libbig / active.fast.c next >
Encoding:
C/C++ Source or Header  |  1992-03-18  |  3.7 KB  |  161 lines

  1. /*
  2.  * active file access functions (big, fast, in-memory version)
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #include "fixerrno.h"
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include "libc.h"
  13. #include "news.h"
  14. #include "config.h"
  15. #include "active.h"
  16.  
  17. /* private */
  18. static char *active = NULL;    /* cache: points at entire active file */
  19. static int actsize;        /* bytes in active: type int fixed by fread */
  20. static char **actlnps;        /* point at lines in active file */
  21. static unsigned actlines;    /* lines in actlnps actually used */
  22.  
  23. /* imports from active.c */
  24. extern char actrelnm[];
  25.  
  26. /* forwards */
  27. FORWARD statust actmkindx();
  28.  
  29. statust
  30. actfload(fp)
  31. FILE *fp;
  32. {
  33.     statust status = ST_OKAY;
  34.  
  35.     if (fp != NULL && active == NULL) {
  36.         struct stat sb;
  37.  
  38.         errno = 0;
  39.         if (fstat(fileno(fp), &sb) < 0)
  40.             warning("can't fstat `%s'", ctlfile(actrelnm));
  41.         else if (actsize = sb.st_size, /* squeeze into an int */
  42.             (unsigned)actsize != sb.st_size)
  43.             warning("`%s' won't fit into memory", ctlfile(actrelnm));
  44.         else if ((active = malloc((unsigned)actsize+1)) == NULL)
  45.             warning("can't allocate memory for `%s'",
  46.                 ctlfile(actrelnm));
  47.         else {
  48.             rewind(fp);
  49.             /*
  50.              * If we read with fgetms, we might be able to avoid
  51.              * calling linescan().
  52.              */
  53.             if (fread(active, 1, actsize, fp) != actsize) {
  54.                 warning("error reading `%s'", ctlfile(actrelnm));
  55.                 status |= ST_DROPPED;
  56.             } else
  57.                 status |= actmkindx();
  58.         }
  59.         if (active == NULL)
  60.             status |= ST_DROPPED;    /* give up! */
  61.         if (status != ST_OKAY) {
  62.             nnfree(&active);
  63.             nnafree(&actlnps);
  64.         }
  65.     }
  66.     return status;
  67. }
  68.  
  69. static statust
  70. actmkindx()            /* build actlnps index for active */
  71. {
  72.     register statust status = ST_OKAY;
  73.     unsigned lnpsz;
  74.     int maxlines;        /* should this really be long? */
  75.  
  76.     active[actsize] = '\0';        /* make a proper string */
  77.     /* +1 for a possible partial line +1 for a dummy to check overflow */
  78.     maxlines = charcount(active, '\n') + 2;
  79.     lnpsz = sizeof(char *) * (long) maxlines;
  80.     if (lnpsz != sizeof(char *) * (long)maxlines ||
  81.         (actlnps = (char **)malloc(lnpsz)) == NULL) {
  82.         warning("`%s' index won't fit in memory", ctlfile(actrelnm));
  83.             status |= ST_DROPPED;
  84.     } else {
  85.         actlnps[maxlines - 2] = "";    /* in case no partial line */
  86.         actlnps[maxlines - 1] = "";    /* end sentinel */
  87.         actlines = linescan(active, actlnps, maxlines);
  88.         if (actlines >= maxlines) {
  89.             (void) fprintf(stderr,
  90.                 "%s: too many newsgroups in `%s' (can't happen)\n",
  91.                 progname, ctlfile(actrelnm));
  92.             status |= ST_DROPPED;
  93.         }
  94.     }
  95.     return status;
  96. }
  97.  
  98. /*
  99.  * Store in lnarray the addresses of the starts of lines in s.
  100.  * Return the number of lines found; if greater than nent,
  101.  * store only nent and return nent.
  102.  * Thus lnarray should be one bigger than needed to detect overflow.
  103.  */
  104. int
  105. linescan(s, lnarray, nent)
  106. char *s;
  107. char **lnarray;
  108. register int nent;
  109. {
  110.     register char **lnarrp = lnarray;
  111.     register int i = 0;
  112.     register char *nlp = s;
  113.  
  114.     if (i < nent)
  115.         *lnarrp++ = nlp;
  116.     while (++i < nent && (nlp = strchr(nlp, '\n')) != NULL && *++nlp != '\0')
  117.         *lnarrp++ = nlp;
  118.     return i;        /* number of addrs stored */
  119. }
  120.  
  121. statust
  122. actfsync(fp)            /* write to disk, fp is open */
  123. FILE *fp;
  124. {
  125.     statust status = ST_OKAY;
  126.  
  127.     rewind(fp);
  128.     if (active != NULL) {
  129.         if (fwrite(active, actsize, 1, fp) != 1)
  130.             status |= ST_DROPPED;    /* serious loss */
  131.         nnfree(&active);
  132.         nnafree(&actlnps);
  133.     }
  134.     return status;
  135. }
  136.  
  137. /* ARGSUSED fp */
  138. char *
  139. actfind(fp, ng, nglen)
  140. FILE *fp;
  141. register char *ng;
  142. register int nglen;
  143. {
  144.     register char *pos;
  145.     register unsigned line = 0;
  146.  
  147.     while (pos = actlnps[line], line++ < actlines && pos[0] != '\0')
  148.         if (STREQN(pos, ng, nglen) && pos[nglen] == ' ')
  149.             return pos;
  150.     return NULL;
  151. }
  152.  
  153. /* ARGSUSED */
  154. statust
  155. actfwrnum(fp, pos)
  156. FILE *fp;
  157. char *pos;
  158. {
  159.     return ST_OKAY;
  160. }
  161.